perm filename PLALCS.FAI[MUS,LCS]1 blob sn#307161 filedate 1977-09-29 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00013 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002		TITLE	SOUND  DOROTHY BENDER MEMORIAL TITLE 1969,69,69, 1975(LCS)*******
C00006 00003		FIND OUT NUMBER OF CHANNELS AND THE SPEED.
C00013 00004		JRST GOTCHA		GO AHEAD
C00018 00005	
C00023 00006	 Accumulators, temp storage
C00026 00007	 Error codes
C00027 00008	 DACINI
C00032 00009	 DACPLA
C00037 00010	 WAIT1 - Wait for a buffer done message
C00039 00011	 DACWAI - Wait for all xfrs to finish
C00040 00012	 DACREL - release the device
C00041 00013	END
C00042 ENDMK
C⊗;
	TITLE	SOUND;  DOROTHY BENDER MEMORIAL TITLE 1969,69,69, 1975(LCS)*******

;************** LOAD WITH 'DACPLA.FAI' ****** (IT MAY BE ON [SIX,MUS] ) *******
;  ******CALL PLAY ***** 

;  ROUTINE TO READ THE OUTPUT FROM THE MUSIC
;  PROGRAM AND CALL THE D-A CONVERTER TO PLAY.
;  
;  NAME OF THE FILE TO BE INPUTTED IS 'TEST.SND'
;  THE FIRST RECORD OF WHICH CONTAINS THE
;  NUMBER OF WORDS OF DATA IN THE ENTIRE DISK FILE.
;  ALSO INCLUDES FUNCTION TO CHECK ON DATADISC - FOR DPYS.

INTERNAL PLAY
entry DACPLA
internal DACINI,DACPLA,DACWAI,DACREL
external DSK6RD,DSK6WR,MESINI,SBFILN
.library JAMLIB.REL[SUB,SYS]
EXTERNAL JOBREL
A   ←   1     ;WORK
B   ←   2     ;WORK
T1  ←   4     ; TEMP FOR ADSMAP (JAM)
REP ← 6;	;FOR REPLAY USETI
P ← 17
↓DSKCHN ←11            ;DISK CHANNEL FOR INPUT
↓ADCHN  ←12            ;D-A CHANNEL FOR OUTPUT
↓SIXCHN ←13            ;SIX CHANNEL FOR RUNNING DAC
PDL:	BLOCK 40
	OPDEF	READCH [51B8]
        OPDEF   MESSAGE[51B8!3B12]

;;EXTERNAL DACINI,DACPLA,DACWAI,DACREL
;External integer procedure DACINI(Integer dskchn,sixchn,dacchn,clock,pack,nchns,waitflag(0));
;External integer procedure DACPLA(Integer stword,nwds,track(0),blk(0));
;External integer procedure DACWAI;
;External integer procedure DACREL;


;;PLAY:	0
BEG:	;CALLI	0,0         ;RESET I/O DEVICES
PLAY:	OPEN 	DSKCHN,[17  ;MODE
		'DSK   '    ;DEVICE NAME
 		0]          ;NO BUFFER HEADERS
	HALT	BEG         ;RESTART IF DEVICE IS UNAVAILABLE

;IRC	MOVE 0,SBFILN		;OUTPUT NAME FROM 'MUSIC' (6-BIT)
;IRC	MOVEM 0,FILE
;;;	MOVE 7,['SND   ']
;;;	MOVE 6,['TEST  ']
	MOVE 6,SBFILN   	;GET FILNAME FROM 'MUSIC'
	MOVE 7,SBFILN+1 ]	;GET EXT.
	SETZM	DIR+3    ;FOR RESTART
;;	MOVE @1(16)	; GET SRATE
;;	IDIVI =12800	;NOW IT IS 0,1,2,4,8 OR 16.
;;	CAIN 4
;;	MOVEI 3		;4 GOES TO 3
;;	CAIN =8
;;	MOVEI 4		;8 GOES TO 4
;;	CAIN =16
;;	MOVEI 5		;16 GOES TO 5
;;	MOVEM SAVSPD	;INIT SAVSPD
	MOVEM 6,DIR
	MOVEM 7,DIR+1


	;FIND OUT NUMBER OF CHANNELS AND THE SPEED.
;;	MOVE A,@(16)		; GET NCHNS FROM MAIN PROG.
;;	SKIPG A		;*****ALL THIS IS FOUND IN HEADER ANYWAY!!!
	MOVEI A,1		;MAKE NCHNS=1 IF IT WASN'T
	DPB	A,[POINT 2,DACPAR,35]
	SETZM REP	; FOR SPEED CHNGS WITH HEADER

SPD:	MESSAGE [ASCIZ/
  SPEED NUM, <CR>, OR "X" /]
	READCH  A
	SETOM REPT#
	CAIE	A,"X"
	JRST .+3
	MESSAGE [ASCIZ/ ****PLEASE DELETE SOUND FILE**** 
/]
	POPJ P,
;;	JRA	16,(16)
	CAIN A,15	; IS IT A CRLF???
	JRST CRLF	; YES
	CAIN A,"R"		;"Rn" REPEATS PLAY n TIMES
	JRST REP3
	CAIG A,"5"		;IS IT 1 - 5?
	JRST SPD2		;YES
	SKIPN DIR+3		;IS THIS THE 1ST TIME THRU?
	JRST SPD		;YES, SO WE NEED A GOOD NUM.
	JRST PLA2		;ELSE GO PLAY SAME AS LAST TIME
REP3:	READCH A		;WHAT FOLLOWS R?
	SUBI A,"0"		;FIX IT UP
	CAILE A,=9		;IF(A.GT.9)A=1  TRAPS "G" ETC.
	MOVEI A,1
	MOVNM A,REPT		
	MOVE A,SAVSPD		;GET BACK SPEED.
	JRST SPD3

CRLF:	READCH A		;GET THE LINEFEED
	MOVE A,SAVSPD
	JRST SPD3
SPD2:	SUBI	A,"0"
	MOVEM A,SAVSPD#		;SAVE AC A.
SPD3:	DPB	A,[POINT 3,DACPAR,26]

PLA2:	SETZM DIR+3
	LOOKUP	DSKCHN,DIR   
	SKIPA			;CAN'T FIND TEST.SND
	JRST XOPEN		;FOUND IT

MUS:	JRST	[MESSAGE[ASCIZ/
		*** TEST.SND NOT FOUND/]
		CALLI  12]
        ;EXIT IF FILE IS MISSING

XOPEN:	OPEN	ADCHN,[1B27+000	;MODE
         	'DAC   '        ;DEVICE NAME
 		0]              ;NO BUFFER HEADERS
	SKIPA
	JRST GOTCHA		;GO AHEAD
        MESSAGE [ASCIZ/
WAITING FOR DAC------ /]
	OPEN  ADCHN,[1B26+000	;WE'LL WAIT FOR IT
		  'DAC   '
		  0]
	0			;NO FAILURE POSSIBLE?????
GOTCHA:	PUSH P,[DSKCHN]
	PUSH P,[SIXCHN]
	PUSH P,[ADCHN]
	LDB B,[POINT 3,DACPAR,26]		;PUT AWAY THE SPEED
	PUSH P,B
	LDB B,[POINT 2,DACPAR,29]			;12 OR 18 BIT
	PUSH P,B
	LDB B,[POINT 2,DACPAR,35]
	PUSH P,B
	PUSH P,[0]		; INTERROGATE USER AND WAIT FOR IT
	PUSHJ P,DACINI
SPWAR:	LOCK A,			;SPWAR:

	MESSAGE [ASCIZ/ GO? /]
	READCH A
	CAIN A,15
	READCH A		;FOR CRLF
	; READS TO FIND (AND IGNORE) HEADER.(1ST REC.)
DOIT:	SKIPE REP		;SKIP FIRST TIME
	JRST REPLA		;OMIT HEADER ON REPLAYS
	MOVEI REP,1 		;FOR REPLAY
	INPUT DSKCHN,HEADER
	MOVEI A,BUF1-1
	MOVE B,1(A)
	CAME B,[525252525252]	; LOOKS FOR MAGIC NUMBER.
	JRST REPLA
	MESSAGE [ASCIZ/
---- THERE'S A HEADER ---- /]
	PUSH P,[DSKCHN]
	PUSH P,[SIXCHN]
	PUSH P,[ADCHN]
	HLRZ B,2(A)			;GET SPEED FROM LEFT HALF OF WD 2
	JUMPN B,SPDOK
	MOVE B,2(A)			;FIND SRATE NUM FOR SPEED
	IDIVI B,=12800
SPDOK:	MOVEM B,SAVSPD
	DPB B,[POINT 3,DACPAR,26]		;PUT AWAY THE SPEED
	PUSH P,B
	HRRZ B,3(A)			;GET BITS FROM RIGHT HALF OF WD 3
	DPB B,[POINT 2,DACPAR,29]			;12 OR 18 BIT
	PUSH P,B
	MOVE B,4(A)			;GET NCHNS FROM WD 4
	DPB B,[POINT 2,DACPAR,35]
	PUSH P,B
	PUSH P,[0]		; INTERROGATE USER IF DAC NOT AVAILABLE
	PUSHJ P,DACINI		; INITIALIZE THE DAC, SET PARAMETERS
	MOVEI REP,2		;FOR REPLAY
REPLA:	USETI DSKCHN,(REP)	;REP=1 IF NO HEADER, =2 WITH HEADER.
LNTH:	movs a,DIR+3		;get length of file.
	CAIN REP,2		;WAS THERE A HEADER?
	ADDI A,200		;YES, SUBTRACT IT FROM WDCNT.
	movnm a,nwd
;-----------------------------------------------------

	;BEGIN MAIN BODY OF PROGRAM

	MOVE T1,[647003,,0]
	ADSMAP T1,	; SET AUDIO SWITCH TEMPORARILY TO DAC (JAM 7/24/75)
			; THE OPTIONS WE ASKED FOR ARE TEMPORARY, WAIT FOR
			; PAGE TO FINISH, DON'T INTERRUPT WITH MORE PAGES,
			; DELAY BEEPS TO END OF XFR.
	OUTSTR [ASCIZ /
TO DAC . . ./]
	PUSH P,REP	; SAVE OVER CALL
	SETZ B,
	CAIN REP,2
	MOVEI B,200
	PUSH P,B
	PUSH P,NWD
	PUSH P,[0]
	PUSH P,[0]
	PUSHJ P,DACPLA
	POP P,REP	; GET REP BACK

DONE:	AOSGE REPT		;UPDATE REPT
	JRST REPLA		;WE PLAY AGAIN IF REPT .LT.0
	PUSHJ P,DACWAI
	PUSHJ P,DACREL
	close dskchn,		;END OF PROGRAM.
;;	SKIPL XGHLD		;FOR GREED'S SAKE
	releas adchn,
;;	OUTSTR [ASCIZ / DONE!
;;/]
	SETO T1,
	ADSMAP T1,	; RESET AUDIO SWITCH CONNECTION TO PERMANENT (JAM 7/24/75)
	UNLOCK
	jrst SPD



; STORAGE:

NWD:	0			;FOR NUMBER OF WORDS OF INPUT.
;↓BUF1:	BLOCK	BUFSIZ+1	;BUFFER 1
;BUF2:	BLOCK	BUFSIZ+1	;BUFFER 2
;BUF3:	BLOCK	BUFSIZ+1	;BUFFER 3
DIR:	0    			;NAME
	0			;EXTENSION
	0			;INFORMATION ON FILE
	0			;PROJECT PROG#
CLIST:	IOWD	1,NWD		;FOR THE FIRST RECORD
	0
INLIST:	0			;WILL CONTAIN AN IOWD
	0
HEADER:	IOWD =128,BUF1
	0
BUF1:	BLOCK =128
OUTWC:	0			;WILL CONTAIN AN IOWD FOR D-A
OUTBIT: 4000			;BITS FOR D-A
	BLOCK	2
DACPAR:	1001		;SPEED 0=6.4K, 1=12.8, 2=25.6, 3=51.2, 4=102.4, 5=
	0
	0


A←1
B←2
D←3

ichn←adchn

comment ⊗

External integer procedure DACINI(Integer dskchn,sixchn,dacchn,clock,pack,nchns,waitflag(0));
External integer procedure DACPLA(Integer stword,nwds,track(0),blk(0));
External integer procedure DACWAI;
External integer procedure DACREL;

DACINI

Must have disk open on channel DSKCHN. It will open the SIX and the DAC. Afterwards
it will set the DAC parameters to CLOCK, PACK, and NCHNS. It will then claim
buffers on the 6 and lock your KL10 job into core. Returns zero or -1 on success:
-1 means it had to wait for the DAC. Returns error 1 for user didn't want to
wait for the DAC and 2 if there was not enough core on the SIX.
The WAITFLAG determines whether DACINI will query the user as to whether he wants
to wait for the DAC. 0 means interrogate user and wait if he asks, 1 means always
wait (without asking) and -1 means never wait, never ask.
Disk must be opened in mode 17 (dump mode). Can be disk, new or old format UDP.
Track and BLK in DACPLA are irrelevant except for old format UDP.
(will get illegal UUO if disk not opened in mode 17).

CLOCK is actually the clock code, not the clock rate. This is 0 for 6.4 Kc,
1 for 12.8 Kc, 2 for 25.6 Kc, 3 for 51.2 Kc, and 4 for 102.4 Kc. This is the
clock rate per channel (not the overall clock rate). Pack should be 0 for
12-bit or 1 for 18-bit.

DACPLA

Queues up the sound in the dsk channel from word number STWORD for a total
of NWDS words. Transfer may still be running when this routine exits.

DACWAI

This waits for any transfers which were running to be finished. After
this call, the DAC will be idle.

DACREL

This releases the DAC, stops any transfer which might be running, and
releases the buffers on the six. It will release the SIX and the DAC.

⊗
; Accumulators, temp storage

↓ac1←4
↓ac2←5
↓ac3←6
↓ac4←7
↓ac5←10
↓ac6←11
↓ac7←13
↓ac8←14
↓ac9←15
↓p←17

.insert MESDEF[SIX,MUS]

adr:	block 2		; For IOWDS and stuff
data:	block 3		; For messages

; Message codes going to DAC

MSPAR←←1010	; SET PARAMETERS. TAKES 9-BIT DATUM
MSTBUF←←1011	; START BUFFER. TAKES WCMA AS DATUM.
MSTOP←←1012	; DROP EVERYTHING
MQBUF←←1013	; QUEUE BUFFER BUT DON'T START IT
MFSTB←←1015	; FIRST BUFFER COMING

; Message codes coming from DAC

MBDONE←←1020	; BUFFER DONE.
MHUNG←←1021	; DEVICE IS HUNG.
MDMISS←←1022	; HARDWARE DATA MISSED SEEN
MBMISS←←1023	; BUFFER MISSED (RAN OFF END WITH NO WCMA READY)
MBOOB←←1025	; BUFFER OUT OF BOUNDS

DACDEV←←2	; DIGITAL-ANALOG CONVERTER DEVICE NUMBER

; = SPEED*1000+PACK*100+NCHANS
; NCHANS = 1 FOR MONO	(2-BIT NUMBER)
;	 = 2 FOR STEREO
;	 = 0,3 FOR QUAD
; PACK = 0,3 FOR 12 BIT  (2-BIT NUMBER)
;      = 1 FOR 16 BIT (HALFWORD MODE)
;      = 2 FOR FLOATING PT. INCREMENTAL
; SPEED = 0 FOR 6.4 KC	(3-BIT NUMBER)
;       = 1 FOR 12.8 KC
;       = 2 FOR 25.6 KC
;       = 3 FOR 51.2 KC
;       = 4 FOR 102.4 KC
;       = 5 FOR 204.8 KC

; Other storage . . .

oldfmt:	0	; 0 for New fmt, ≠0 for old fmt udp
wcmas:
wcma1:	0	; WCMA for buffer 1
wcma2:	0	; for buffer 2
wcma3:	0	; Set to zero if not needed
nxtwc:	0	; 0, 1, or 2, for next buffer to fill
nq:	0	; Number of xfrs in queue now (0, 1, 2, or 3)

dacchn:	0	; Channel number for DAC
;;sixchn:	0	;    " for SIX
;;dskchn:	0	;    " for DSK

trklen←←=18*=128	; Length of track for new fmt UDP or DSK
otrklen←←40+trklen	; Same for old fmt UDP
↓ntrks←←6		; Number of tracks per buffer
;↓ntrks←←10		; Number of tracks for SIXSYS without DDT
waited:	0	; Set to -1 if we waited for DAC
; Error codes

enodac←←1	; User doesn't want to wait for DAC
enocor←←2	; Not enuf core on PDP-6
didwait←←-1	; Did have to wait for DAC
; DACINI
;External integer procedure DACINI(Integer dskchn,sixchn,dacchn,clock,pack,nchns,waitflag(0));

DACINI:	begin DACINI

watloc←←-1
ncloc←←-2
pakloc←←-3
clkloc←←-4
dacloc←←-5
sixloc←←-6
dskloc←←-7
pd←←10

nowait←←400
wait←←1000

	setzm waited
	move ac1,dskloc(p)
	movem ac1,dskchn
	dpb ac1,[point 4,dskc1,12]

	devchr ac1,		; if 100000 bit in LH is on, and
				; 200000 bit is off, is old-style udp
	setom oldfmt
	tlne ac1,100000
	tlne ac1,200000
	setzm oldfmt

	move ac1,sixloc(p)
	movem ac1,sixchn
	dpb ac1,[point 4,sixc1,12]
	dpb ac1,[point 4,sixc2,12]
	dpb ac1,[point 4,sixc3,12]
	dpb ac1,[point 4,sixc4,12]
	dpb ac1,[point 4,sixc5,12]
	dpb ac1,[point 4,sixc6,12]
	dpb ac1,[point 4,sixc7,12]
	dpb ac1,[point 4,sixc8,12]
	dpb ac1,[point 4,sixc9,12]
	dpb ac1,[point 4,sixc10,12]
	dpb ac1,[point 4,sixc11,12]
	dpb ac1,[point 4,sixc12,12]
	dpb ac1,[point 4,sixc13,12]
	dpb ac1,[point 4,sixc14,12]
	push p,ac1
	pushj p,mesini

	move ac1,dacloc(p)
	movem ac1,dacchn
	dpb ac1,[point 4,dacc1,12]
	dpb ac1,[point 4,dacc2,12]
	dpb ac1,[point 4,dacc3,12]
	dpb ac1,[point 4,dacc4,12]

dacc1:	init 0,nowait
	sixbit /DAC/
	0
	jrst [move ac1,watloc(p)
	      jumpl ac1,nodacx
	      jumpg ac1,dacc2
	      outstr [asciz /
DAC is busy. Will you wait?	/]
	      inchwl ac1
	      pushj p,rdlf
	      caie ac1,"y"
	      cain ac1,"Y"
	      jrst dacc2
nodacx:	      movei 1,enodac		; Give "no DAC" error message
	      jrst xit]
sixc1:	init 0,17
	sixbit /SIX/
	0
	jrst 4,.
			; = SPEED*1000+PACK*100+NCHANS
	move ac1,[mspar,,dacdev]
	movem ac1,data
	movsi ac1,1
	movem ac1,data+1
	move ac1,clkloc(p)
	lsh ac1,=3
	or ac1,pakloc(p)
	lsh ac1,=6
	or ac1,ncloc(p)
	movem ac1,data+2
	move ac1,[iowd 3,data]
	movem ac1,adr
	setzm adr+1
sixc2:	output 0,adr

	movei ac1,ntrks*trklen
	skipe oldfmt
	movei ac1,ntrks*otrklen	; Get 4 tracks per buffer
	movem ac1,data+2
	movsi ac1,mgbuf
	hllm ac1,data
sixc3:	output 0,adr
sixc4:	output 0,adr
sixc5:	output 0,adr		; Ask for 3 buffers of identical size.
	movei ac2,2
sixc6:	input 0,adr		; Wait for message to come back
	hlrz ac1,data
	trne ac1,fncomp!fdmissed
	jrst [outstr [asciz /DACINI - Incomplete message from PDP-6
/]
	      jrst mbtest]
mbtest:	caie ac1,f6to10!mgbuf		; Ignore everything but buffer reply
	jrst sixc6
	skipl ac1,data+2
	jrst nocore		; Hmmm. No core?
	movem ac1,wcmas(ac2)
	sojge ac2,sixc6
	setzm nq		; Clear number of buffers in queue
	setzm nxtwc

	setz 1,
	skipe waited
	move 1,[didwait]	; Give -1 return for waited
xit:	adjsp p,-pd
	jrst @pd(p)

dacc2:	init 0,wait
	sixbit /DAC/
	0
	jrst 4,.
	setom waited
	jrst sixc1

nocore:	movsi ac1,mdblast	; Forget everything we ever know about device
	hllm ac1,data
	move ac1,[iowd 1,data]
	movem ac1,data+1
sixc7:	output 0,adr
	movei 1,enocore
dacc3:	release 0,		; Release dummy DAC device
	setzm wcma1
	setzm wcma2
	setzm wcma3
	jrst xit

rdlf:	cain ac1,12
	popj p,
rdlf1:	inchwl ac9
	cain ac9,175
	jrst isalt
	caie ac9,12
	jrst rdlf1
	popj p,

isalt:	outstr [asciz /
/]
	popj p,

bend DACINI
; DACPLA
;External integer procedure DACPLA(Integer stword,nwds,track(0),blk(0));

; Uses . . .

;External procedure DSK6RD(integer dchan,nwds,p3addr,track(0),blk(0));
;External procedure DSK6WR(integer dchan,nwds,p3addr,track(0),blk(0));

;DAC may be running when we enter.

DACPLA:	begin DACPLA

integer offset		; Number of words in first buffer to be ignored
integer track
integer block		; For old mode
integer nwltt		; Number of words left this track
integer ndwfb		; Number of words in first buffer (from disk) total
integer nwfb		; Number of data words in first buffer (for DAC)

blkloc←←-1
trkloc←←-2
nwdloc←←-3
stwloc←←-4
pd←←5

	setz 1,
	skipg nwdloc(p)		; Anybody home?
	jrst xit		; No, leave now
	skipe wcma1
	skipn wcma2
	jrst [movei 1,enocore
	      jrst xit]
	skipn wcma3
	jrst [movei 1,enocore
	      jrst xit]

	skipe oldfmt
	jrst isold
	move ac1,stwloc(p)
	move ac2,ac1
	andi ac2,177
	movem ac2,offset
	lsh ac1,-7
	addi ac1,1
↑dskc1:	useti 0,(ac1)

	move ac1,stwloc(p)
	idivi ac1,trklen
	movn ac2,ac2
	addi ac2,trklen
	movem ac2,nwltt

	addi ac2,<ntrks-1>*trklen
	movem ac2,nwfb
	jrst allgo

isold:	move ac1,trkloc(p)
	imuli ac1,otrklen
	move ac2,blkloc(p)
	caige ac2,1
	jrst nocorr
	addi ac1,40
	subi ac2,1
	lsh ac2,7
	addi ac1,(ac2)		; Convert to word number on UDP
nocorr:	add ac1,stwloc(p)
	idivi ac1,otrklen	; And back to track-block
	movem ac1,track
	movni ac3,(ac2)		; Pick up number of words used this track
	addi ac3,otrklen
	movem ac3,nwltt		; Set number words left this track
	addi ac3,<ntrks-1>*otrklen
	movem ac3,nwfb
	caige ac2,40
	jrst [setzm block
	      jrst setoff]
	subi ac2,40
	move ac1,ac2
	andi ac2,177
	lsh ac1,-7
	addi ac1,1
	movem ac1,block
setoff:	movem ac2,offset

allgo:	push p,dskchn
	move ac1,nwfb
	camle ac1,nwdloc-1(p)
	move ac1,nwdloc-1(p)	; Don't do any more than we have to!
	movem ac1,ndwfb
	add ac1,offset		; Make sure we get all of first record
	push p,ac1
	move ac2,nxtwc
	hrrz ac1,wcmas(ac2)
	push p,ac1
	push p,track
	push p,block
	move ac1,nq		; How many are queued?
	cail ac1,3		; If more than 3, must wait
	pushj p,wait1		; Wait until that first buffer is free
	pushj p,dsk6rd		; Fill it

	move ac2,nxtwc		; Pick up buffer number (0, 1, or 2)
	movn ac1,ndwfb		; This has been truncated to length of file
	addm ac1,nwdloc(p)	; Note that many more words gone by
	movs ac1,ac1		; Make up WCMA for transfer
	hrr ac1,wcmas(ac2)	; Put address of buffer on 6 in RH
	add ac1,offset		; Offset for partial first buffer (if any)
	movem ac1,data+2
	move ac1,[mstbuf,,dacdev]
	movem ac1,data
	movsi ac1,1
	movem ac1,data+1
	move ac1,[iowd 3,data]
	movem ac1,adr
↑sixc8:	output 0,adr
	aos nq			; Note one more in the queue
	sosge ac1,nxtwc
	movei ac1,2
	movem ac1,nxtwc
	skipg nwdloc(p)
	jrst alldone

	setzm offset
	movei ac1,ntrks*trklen
	skipe oldfmt
	movei ac1,ntrks*otrklen
	movem ac1,nwfb

	movei ac1,ntrks
	addm ac1,track
	setzm block
	jrst allgo

alldone:setz 1,
xit:	adjsp p,-pd
	jrst @pd(p)

bend DACPLA
; WAIT1 - Wait for a buffer done message

WAIT1:	move ac1,[iowd 3,data]
	movem ac1,adr
sixc9:	input 0,adr
	hlrz ac1,data
	trne ac1,fncomp!fdmissed
	jrst [outstr [asciz /DACPLA - incomlete message from 6!
/]
	      jrst wattst]
wattst:	andi ac1,7777
	cain ac1,mhung
	jrst [outstr [asciz /DACPLA - DAC is HUNG!
/]
	      jrst gotit]	; Hung message takes place of done message
	cain ac1,mboob
	jrst [outstr [asciz /DACPLA - buffer out of bounds?!?!!?
/]
	      jrst gotit]	; this message also takes place of done message
	cain ac1,mdmiss
	jrst [outstr [asciz /DACPLA - DAC Data missed!
/]
	      jrst sixc9]
	cain ac1,mbmiss
	jrst [outstr [asciz /DACPLA - DAC buffer missed!
/]
	      jrst sixc9]
	caie ac1,mbdone
	jrst sixc9
gotit:	sosl nq			; Note one less in queue
cpopj:	popj p,
	outstr [asciz /DACPLA - Buffer queue underflow
/]
	jrst 4,cpopj
; DACWAI - Wait for all xfrs to finish

DACWAI:	skipg nq
	jrst sfstbm
	pushj p,wait1
	jrst dacwai

sfstbm:	move ac1,[fnowds!mfstb,,dacdev]
	movem ac1,data
	move ac1,[iowd 1,data]
	movem ac1,adr
sixc14:	output 0,adr		; Clear "buffers finished" count
	popj p,
; DACREL - release the device

DACREL:	move ac1,[iowd 1,data]
	movem ac1,adr
	move ac1,[fnowds!mdblast,,dacdev]
	movem ac1,data
sixc10:	output 0,adr
	move ac1,[iowd 3,data]
	movem ac1,adr
	move ac1,wcma1
	movem ac1,data+2
	move ac1,[mgivb,,dacdev]
	movem ac1,data
	movsi ac1,1
	movem ac1,data+1
sixc11:	output 0,adr
	move ac1,wcma2
	movem ac1,data+2
sixc12:	output 0,adr
	move ac1,wcma3
	movem ac1,data+2
sixc13:	output 0,adr
	setzm wcma1
	setzm wcma2
	setzm wcma3
dacc4:	release 0,
	popj p,
END